package com.chen.config;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.chen.entity.Permission;
import com.chen.entity.User;
import com.chen.mapper.UserMapper;
import com.chen.service.PermissionService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Component
public class DBUserDetailsManager implements UserDetailsManager, UserDetailsPasswordService {


    @Resource
    private UserMapper userMapper;
    @Autowired
    private PermissionService permissionService;


    @Override
    public UserDetails updatePassword(UserDetails user, String newPassword) {
        return null;
    }

    @Override
    public void createUser(UserDetails user) {

        //判断在数据库中是否已经存储对应的用户
        String username = user.getUsername();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User DBUser = userMapper.selectOne(queryWrapper);
        if (DBUser != null) {
            Assert.isTrue(!this.userExists(user.getUsername()), "user should not exist");
        } else {
            DBUser = new User();
            DBUser.setUsername(username);
            DBUser.setEnabled(true);
            DBUser.setPassword(user.getPassword());
            userMapper.insert(DBUser);
        }
    }

    @Override
    public void updateUser(UserDetails user) {

    }

    @Override
    public void deleteUser(String username) {

    }

    @Override
    public void changePassword(String oldPassword, String newPassword) {

    }

    @Override
    public boolean userExists(String username) {
        return false;
    }

//    @Override
//    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//        LambdaQueryWrapper<User> wrapper=new LambdaQueryWrapper<>();
//        //第一个参数是数据库的列名, 如果不一样可以用   @TableField("数据库字段名")这个注解
//        wrapper.eq(User::getUsername, username);
//        User user = userMapper.selectOne(wrapper);
//        // 角色列表先为空
//        Collection<GrantedAuthority> authorities=new ArrayList<>();
//        //模拟从数据库中查出来权限
//        authorities.add(()->"USER_ADD");
////        authorities.add(()->"USER_LIST");
//        if (user == null) {
//            throw new UsernameNotFoundException("user '" + username + "' not found");
//        } else {
//            // 直接给用户授予权限
//            //在RBAC ,基于角色的权限管理中, 用这种方式, 通过user可以查到role, 在通过role就可以得到具体的权限,然后动态赋值
////            return (UserDetails) (user instanceof CredentialsContainer ? user : new org.springframework.security.core.userdetails.User(
////                    user.getUsername(),
////                    user.getPassword(),
////                    user.getEnabled(),
////                    //我们自己的User只有前三个字段
////                    //后面没有,都给默认值
////                    true,//用户是否过期
////                    true,   //用户证书是否过期
////                    true, //是否被禁用
////                    authorities));
//            //给用户授予角色
//            return  org.springframework.security.core.userdetails.User
//                    .withUsername(user.getUsername())
//                    .password(user.getPassword())
//                    .disabled(!user.getEnabled())
//                    .accountExpired(false)
//                    .accountLocked(false)
//                    .roles("ADMIN")
//                  // .authorities("USER_ADD") //会吧roles给覆盖掉
//                    .build();
//            //    public static UserBuilder withUserDetails(UserDetails userDetails) {
//            //        return withUsername(userDetails.getUsername()).password(userDetails.getPassword()).accountExpired(!userDetails.isAccountNonExpired()).accountLocked(!userDetails.isAccountNonLocked()).authorities(userDetails.getAuthorities()).credentialsExpired(!userDetails.isCredentialsNonExpired()).disabled(!userDetails.isEnabled());
//            //    }
//
//
//        }
//    }

    /**
     * 从数据库中查询, 用户-角色-权限
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        //第一个参数是数据库的列名, 如果不一样可以用   @TableField("数据库字段名")这个注解
        wrapper.eq(User::getUsername, username);
        User user = userMapper.selectOne(wrapper);
        //根据user_id查询对应的权限
        List<Permission> permissions = permissionService.listPermissionByUserId(user.getUserId());

        // 初始化列表先为空
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        for (Permission permission : permissions) {
            authorities.add(() -> permission.getPermissionName());
        }
        //模拟从数据库中查出来权限
//        authorities.add(() -> "USER_ADD");
//        authorities.add(()->"USER_LIST");
        if (user == null) {
            throw new UsernameNotFoundException("user '" + username + "' not found");
        } else {
            // 直接给用户授予权限
            //在RBAC ,基于角色的权限管理中, 用这种方式, 通过user可以查到role, 在通过role就可以得到具体的权限,然后动态赋值
            return (UserDetails) (user instanceof CredentialsContainer ? user : new org.springframework.security.core.userdetails.User(
                    user.getUsername(),
                    user.getPassword(),
                    user.getEnabled(),
                    //我们自己的User只有前三个字段
                    //后面没有,都给默认值
                    true,//用户是否过期
                    true,   //用户证书是否过期
                    true, //是否被禁用
                    authorities));

        }
    }
}
